\chapter{Implementação de um driver JDBC}
\label{chap:jdbc-driver-impl}

Este capítulo apresenta as linhas gerais da implementação do driver JDBC do tipo 4 para o \gls{dbms} Microsoft SQL Server 2008 \cite{SQLServer2008}. A informação aqui contida refere-se particularmente ao driver desenvolvido neste trabalho.

Apesar do JDBC ser uma Client Level Interface, e dar por isso a possibilidade de se interacção directa com o \gls{databaseengine}, este trabalho não contempla optimizações que têm como origem a utilização de funcionalidades próprias do DBMS utilizado. 
Pretende-se antes encontrar um modelo de optimização no que se refere ao acesso concorrente de objectos JDBC partilhados. Neste caso em particular, o objectivo centra-se em partilhar um objecto \gls{ResultSet}.
Encontrando um modelo de acesso que prova ser eficiente, independentemente do database engine sobre o qual se está a trabalhar, criam-se condições para que esse modelo seja mais largamente aceite, e possa ser utilizado na implementação de drivers JDBC para os diversos sistemas de base de dados existentes.

O desenho e implementação deste driver é focalizado na componente cliente que o constitui, deixando a componente servidor o mais abstracta possível.
A única componente específica referente à componente servidor, consiste na interface de comunicação com este. Mais propriamente utiliza-se o protocolo de comunicação com o SQL Server (protocolo \gls{tds} (\glssymbol{tds})), e utiliza-se a interface programática existente para efectuar diversas operações com um cursor do servidor, tais como a sua declaração ou a obtenção de uma linha específica do result set (conjunto de linhas seleccionadas pela \gls{statement}).
Esta especialização da componente servidor era inevitável para se conseguir criar um driver JDBC funcional, que possibilitasse testar o seu desempenho.
\hfill \\

O driver implementa duas camadas: JDBC e TDS. A camada JDBC refere-se ao conjunto de classes que implementam as interfaces definidas na API JDBC \cite{JDBCAPI}. A camada TDS refere-se ao conjunto de classes e interfaces que implementam o protocolo de comunicação com SQL Server, o \gls{tds} \cite{MSTDS,SYBASETDS}.

A arquitectura geral de um driver JDBC do tipo 4 para SQL Server 2008 é apresentada na Figura \ref{fig:jdbc-driver-arch}. O driver JDBC converte os pedidos de acesso à API JDBC em invocações à camada TDS, que conhece o modo como os pedidos devem ser realizados ao SQL Server e converte esses pedidos em mensagens do protocolo TDS.

\begin{figure}[H]
  \centering
  \caption{Arquitectura de um driver JDBC do tipo 4 para SQL Server 2008.}
  \label{fig:jdbc-driver-arch}
  \includegraphics[width=5cm]{images/model/jdbc-driver-arch}
\end{figure}


\section{Camada TDS}

A camada TDS do driver JDBC constitui a implementação do protocolo \gls{tds}, que consiste no protocolo de transporte de informação entre uma aplicação cliente e o SQL Server.

Esta secção apenas descreve a interface que esta camada disponibiliza. No apêndice \ref{ap:tds} é fornecida uma resumida descrição do protocolo. Informação mais detalhada sobre o protocolo pode ser obtida nas páginas MSDN dedicadas ao TDS \cite{MSTDS} ou na especificação da Sybase \cite{SYBASETDS}.

A camada TDS fornece duas entidades que permitem à camada superior interagir com o SQL Server sem conhecer as especificidades do protocolo: \emph{TDSMessage} e \emph{ITDSResultSet}. 

\subsection{TDSMessage}

A classe TDSMessage implementa toda a comunicação com o servidor. A comunicação é realizada utilizando um socket TCP. 

Os serviços disponibilizados pela classe TDSMessage consistem em invocações de serviços do SQL Server. A classe converte os pedidos da camada superior na linguagem do SQL Server. A Figura \ref{fig:tdsmessage} apresenta os serviços disponibilizados pela classe.

\begin{figure}[H]
  \centering
  \caption{Classe TDSMessage.}
  \label{fig:tdsmessage}
  \includegraphics[width=13cm]{images/model/tdsmessage}
\end{figure}

A classe \emph{UpdateValue} que é utilizada nos métodos cursorUpdate, cursorUpdateAbsolute, cursorDelete, cursorDeleteAbsolute e cursorInsert, tem como objectivo converter os valores das colunas de uma linha no formato do protocolo. Converte o valor de um tipo de dados Java num conjunto de bytes formatados de acordo com o TDS, o resultado é depois transferido para o SQL Server na mensagem (actualização, remoção ou inserção).

A Tabela \ref{tab:tdsmessage} apresenta uma sucinta descrição dos serviços da classe TDSMessage.

\begin{center}
  \small
  \begin{longtable}{|l|p{10cm}|}
  \caption{Descrição dos serviços da classe TDSMessage}
  \label{tab:tdsmessage}
  \\ \hline
  \head{Nome} & \head{Descrição}
  \\ \hline
  \endhead
  \texttt{close} & Fecha os streams de comunicação com o servidor.
  \\ \hline
  \texttt{login} & Envia um pedido de login ao servidor.
  \\ \hline
  \texttt{executeSQLBatch} & Envia um pedido de execução de um \gls{batch} de comandos SQL ao servidor.
  \\ \hline
  \texttt{cursorClose} & Envia um pedido ao servidor para fechar e desalocar um cursor.
  \\ \hline
  \texttt{cursorOpen} & Envia um pedido ao servidor para alocar e abrir um cursor.
  \\ \hline
  \texttt{cursorUpdate} & Envia um pedido ao servidor de actualização de valores das colunas de uma linha, considerando uma posição relativa.
  \\ \hline
  \texttt{cursorUpdateAbsolute} & Envia um pedido ao servidor de actualização de valores das colunas de uma linha, considerando uma posição absoluta.
  \\ \hline
  \texttt{cursorDelete} & Envia um pedido ao servidor de remoção de uma linha, considerando uma posição relativa.
  \\ \hline
  \texttt{cursorDeleteAbsolute} & Envia um pedido ao servidor de remoção de uma linha, considerando uma posição absoluta.
  \\ \hline
  \texttt{cursorInsert} & Envia um pedido ao servidor de inserção de uma linha.
  \\ \hline
  \texttt{cursorFetch} & Envia um pedido ao servidor de carregamento de linhas do result set.
  \\ \hline
  \texttt{cursorRefresh} & Envia um pedido ao servidor de recarregamento de linhas do result set.
  \\ \hline
  \texttt{cursorRows} & Envia um pedido ao servidor de informação relativamente ao número total de linhas do result set do cursor.
  \\ \hline
  \end{longtable}
\end{center}

\subsection{ITDSResultSet}

Quando o servidor envia ao cliente um result set\footnote{Resultado da execução de uma \gls{statement}}, este vem formatado de acordo com o protocolo. A interface ITDSResultSet fornece serviços para extrair a informação do result set, garantindo acesso aos dados sem a necessidade do conhecimento dos detalhes. 

A Figura \ref{fig:itdsresultset} apresenta os serviços fornecidos pela interface ITDSResultSet.

\begin{figure}[H]
  \centering
  \caption{Interface ITDSResultSet.}
  \label{fig:itdsresultset}
  \includegraphics[width=12cm]{images/model/itdsresultset}
\end{figure}

A descrição dos serviços da interface ITDSResultSet é apresentada na Tabela \ref{tab:itdsresultset}.

\begin{center}
  \small
  \begin{longtable}{|l|p{10cm}|}
  \caption{Descrição dos serviços da interface ITDSResultSet}
  \label{tab:itdsresultset}
  \\ \hline
  \head{Nome} & \head{Descrição}
  \\ \hline
  \endhead
  \texttt{getCursor} & Obtém o identificador do cursor do servidor.
  \\ \hline
  \texttt{columnCount} & Obtém a quantidade de colunas que cada linha do result set possui.
  \\ \hline
  \texttt{rowCount} & Obtém a quantidade de linhas que foram enviadas para o cliente.
  \\ \hline
  \texttt{isEmpty} & Verifica se a quantidade de linhas é zero.
  \\ \hline
  \texttt{getXXX} & Obtém o valor de uma coluna, dado o seu índice. Existe um método get para cada um dos tipos de dados Java suportados: int, double, String e Date.
  \\ \hline
  \texttt{wasNull} & Verifica se o valor da coluna lido é SQL NULL.
  \\ \hline
  \texttt{insertRow} & Insere uma linha na cópia do result set que existe no cliente.
  \\ \hline
  \texttt{updateRow} & Actualiza uma linha da cópia do result set que existe no cliente.
  \\ \hline
  \texttt{getColumnName} & Obtém o nome de uma coluna, dado o seu índice.
  \\ \hline
  \texttt{getUpdateRowCount} & Obtém o número de linhas que foram alteradas na base de dados como resultado da execução de um comando \glssymbol{dml}.
  \\ \hline
  \end{longtable}
\end{center}

\section{Camada JDBC}

Esta camada é constituída por um conjunto de classes que implementam as interfaces definidas na API JDBC. 

Neste trabalho procedeu-se apenas a uma implementação parcelar da API. Um dos objectivos principais para o driver JDBC era suportar a execução de \glspl{statement} e obter acesso a um result set. A Tabela \ref{tab:jdbc-impl} lista as interfaces que foram implementadas e identifica as classes que as implementam. As interfaces implementadas pertencem todas ao pacote \texttt{java.sql}.

No capítulo \ref{chap:cresultset} é apresentada uma explicação mais detalhada da implementação da interface ResultSet.

\begin{center}
  \small
  \begin{longtable}{|l|l|p{10.5cm}|}
  \caption{Interfaces da API JDBC implementadas.}
  \label{tab:jdbc-impl}
  \\ \hline
  \head{Interface} & \head{Classe} & \head{Descrição}
  \\ \hline
  \endhead
  Driver & CDriver & Esta interface tem que ser obrigatoriamente implementada por um driver. A classe java.sql.DriverManager encarrega-se de carregar os drivers, que mais tarde serão usados para criar uma ligação à base de dados.
  \\ \hline
  Statement & CStatement & Esta interface permite executar \glspl{statement} e obter o respectivo result set.
  \\ \hline
  ResultSet & CResultSet & Esta interface permite obter acesso ao resultado da execução de uma \gls{statement}. Existem serviços para leitura e modificação do result set.
  \\ \hline
  \end{longtable}
\end{center}
